//
//  ACORMObjectProtocol.h
//  ACCache_Example
//
//  Created by autohome on 2021/7/29.
//  Copyright © 2021 CaiXiang. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import "NSObject+ACORMExtension.h"

NS_ASSUME_NONNULL_BEGIN

@protocol ACORMObjectProtocol <NSObject>

@required

/// 为数据库建表提供数据
- (NSArray <NSString *>*)ac_dbTableProperty;

@optional

/// 黑名单 不存入数据库的字段，
/// 默认是遍历获取模型的全部字段
- (NSArray <NSString *>*)ac_blackList;

/// 自定义主键 保证单条数据的唯一性
- (NSString *)ac_customPrimarykey;

/// 自定义序列化列表 内部只处理了 
+ (NSDictionary<NSString *,NSString *> *)ac_customArchiveDictionary;

/// 自定义序列化解档方法
/// @param data 从数据库中取出的data
/// @param propertyName 属性名称
- (void)ac_unarchiveSetData:(id)data property:(NSString*)propertyName;

/// 自定义序列化归档方法
/// @param propertyName 属性名称
- (id)ac_archiveProperty:(NSString*)propertyName;

///  在使用ACORM_IMPLEMENTATION_INJECT宏的情况下,
///  模型类中如需额外初始化请实现'ac_init'. 或者自定义其他构造方法.调用 '[super init]'
- (void)ac_init;

@end

#define ACORM_IMPLEMENTATION_INJECT(clazz)\
{\
    NSMutableArray *_ac_properties;\
}\
- (instancetype)init {\
    self = [super init];\
    if (self) {\
        _ac_properties = [NSMutableArray array];\
        [self ac_loadAllProperties];\
        if ([self respondsToSelector:@selector(ac_init)]) {\
            [self ac_init];\
        }\
    }\
    return self;\
}\
\
- (NSArray*)ac_dbTableProperty {\
    return _ac_properties;\
}\
\
- (void)ac_loadAllProperties {\
    u_int count;\
    objc_property_t *properties = class_copyPropertyList([self class], &count);\
    NSMutableArray *defaultBlackList = [NSMutableArray array];\
    [defaultBlackList addObject:@"hash"];\
    [defaultBlackList addObject:@"superclass"];\
    [defaultBlackList addObject:@"description"];\
    [defaultBlackList addObject:@"debugDescription"];\
    if ([self respondsToSelector:@selector(ac_blackList)]) {\
        NSArray *blackList = [self ac_blackList];\
        if (blackList.count > 0) {\
            [defaultBlackList addObjectsFromArray:blackList];\
        }\
    }\
    for (int i = 0; i < count ; i++)    {\
        const char* propertyName = property_getName(properties[i]);\
        NSString *proNameStr = [NSString stringWithUTF8String: propertyName];\
        if (![defaultBlackList containsObject:proNameStr]) {\
            [_ac_properties addObject:proNameStr];\
        }\
    }\
    NSAssert(_ac_properties.count > 0, @"ACORMObjectProtocol The protocol object property field is insufficient to create the database table!");\
    free(properties);\
}\


NS_ASSUME_NONNULL_END
